package com.tianji.learning.utils;

import lombok.Data;

import java.time.Duration;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * DelayTask类实现了Delayed接口，用于表示带有延迟的任务。
 * 该类包含一个泛型数据类型D和任务的截止时间。
 *
 * @param <D> 泛型类型，用于表示任务的数据
 */
@Data
public class DelayTask<D> implements Delayed {
    private D data; // 任务的数据
    private long deadlineNanos; // 任务的截止时间，以纳秒为单位

    /**
     * 构造函数，初始化任务数据和延迟时间
     *
     * @param data 任务的数据
     * @param delayTime 任务的延迟时间
     */
    public DelayTask(D data, Duration delayTime) {
        this.data = data;
        this.deadlineNanos = System.nanoTime() + delayTime.toNanos(); // 当前时间加上延迟时间
    }

    /**
     * 获取任务的延迟时间
     *
     * @param unit 时间单位
     * @return 返回以指定时间单位表示的延迟时间
     */
    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(Math.max(0, deadlineNanos - System.nanoTime()), TimeUnit.NANOSECONDS); // 计算剩余延迟时间
    }


    /**
     * 在这个实现中，使用了 getDelay(TimeUnit.NANOSECONDS) 方法来获取两个任务的剩余延迟时间，然后进行比较：
     *
     * 如果当前任务的剩余延迟时间较长，返回正数（1）。
     * 如果当前任务的剩余延迟时间较短，返回负数（-1）。
     * 如果两个任务的剩余延迟时间相等，返回零（0）。
     * 这种比较方法可以确保 DelayQueue 按照任务的剩余延迟时间排序，从而使最早到期的任务最先处理。
     * @param o the object to be compared.
     * @return
     */
    @Override
    public int compareTo(Delayed o) {
        long l = getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS); // 比较两个任务的剩余延迟时间
        if(l > 0){
            return 1;
        }else if(l < 0){
            return -1;
        }else {
            return 0;
        }
    }
}
